import 'dart:async';
import 'dart:convert';

import 'package:custom_pop_up_menu/custom_pop_up_menu.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'package:flutter_chat_ui/mixin/chat_mixin.dart';
import 'package:flutter_chat_ui/models/chat_message_model.dart';
import 'package:flutter_chat_ui/models/chat_room_info_mode.dart';
import 'package:flutter_chat_ui/models/chat_session_model.dart';
import 'package:flutter_chat_ui/utils/getx_update_keys.dart';
import 'package:flutter_chat_ui/utils/utils.dart';
import 'package:get/get.dart';
import 'package:logger/web.dart';

typedef ChatMap = Map<String, dynamic>;
typedef ChatStream = (String, ChatMap);

///
/// 聊天控制器
///
class ChatRoomController extends GetxController with ChatReuqestMixin {
  static ChatRoomController get to => Get.find<ChatRoomController>();

  /// 标记用户是否正在手动拖拽ListView，true：是，false：否
  bool isUserDragging = false;

  /// 记录当前机器人回答的taskId【用于 停止机器人响应】
  String? currentTaskId;

  /// 记录机器人的欢迎语【推荐问题】
  ChatMessageData? welcomeData;

  /// 是否以流的方式返回
  bool isStream = true;

  /// 聊天室信息
  final chatRoomInfoData = ChatRoomInfoData().obs;
  final barTitle = ''.obs;

  /// 聊天消息
  List<ChatMessageData> chatMessages = [];

  /// 会话记录
  List<ChatSessionData> chatSessionList = [];

  /// 缓存每个会话对应菜单管理器
  Map<String, CustomPopupMenuController> chatSessionMenuControllerMap = {};

  /// 机器人是否正在响应输出
  final isResponding = false.obs;

  /// 文本框是否为空
  final isTextEmpty = true.obs;

  @override
  void onInit() {
    ///

    super.onInit();
  }

  @override
  void onReady() {
    /// 获取聊天室信息
    requestGetAppInfo(
      success: (data) {
        if (data != null) {
          chatRoomInfoData.value = data;
          barTitle.value = data.name ?? '';
        }
      },
      fail: (code, msg) {},
    );

    /// 获取应用参数
    requestGetAppParams(
      success: (data) {
        if (data != null) {
          // 默认添加机器人的欢迎语
          if (data.suggestedQuestions.isNotEmpty) {
            final welcome = ChatMessageData(
              event: MessageEventType.welcome.event,
              messageId: Utils.getUniqueId(),
              createdAt: DateTime.now().millisecondsSinceEpoch,
              openingRemarksData: data,
            );
            chatMessages.add(welcome);
            // 记录欢迎语
            welcomeData = welcome;
            // 更新UI
            update([GetxUpdateKeys.chatListId]);
          }
        }
      },
      fail: (code, msg) {},
    );

    /// 获取会话记录
    requestGetChatList(
      userId: Utils.userId,
      success: (data) {
        chatSessionList = data?.data ?? [];
        // 更新UI
        update([GetxUpdateKeys.chatSessionListId]);
      },
      fail: (code, msg) {},
    );

    super.onReady();
  }

  ///
  /// 获取缓存中的会话菜单管理器
  ///
  CustomPopupMenuController getChatSessionMenuController(String conversationId) {
    final controller = chatSessionMenuControllerMap.putIfAbsent(conversationId, () => CustomPopupMenuController());
    return controller;
  }

  ///
  /// 销毁对应会话的菜单管理器
  ///
  void disposeChatSessionMenuController(String conversationId) {
    if (chatSessionMenuControllerMap.containsKey(conversationId)) {
      chatSessionMenuControllerMap.remove(conversationId);
    }
  }

  ///
  /// 发送消息
  ///
  /// conversationId:（选填）会话 ID，需要基于之前的聊天记录继续对话，必须传之前消息的 conversation_id。
  ///
  /// inputs: (选填) 工作流中必填参数
  /// { "cityCode": "350100", "token": "xxx", "lng": "xxx", "lat": "xxx"}
  ///
  void sendMessage(
    String query, {
    String conversationId = '',
    Map<String, dynamic>? inputs,
  }) {
    isUserDragging = false;

    /// 处理输入框发送、暂停按钮逻辑
    isTextEmpty.value = true;
    Future.delayed(
      const Duration(milliseconds: 250),
      () => isResponding.value = true,
    );
    // 添加主人的消息
    chatMessages.insert(
      0,
      ChatMessageData(
        event: MessageEventType.master.event,
        messageId: Utils.getUniqueId(),
        createdAt: DateTime.now().millisecondsSinceEpoch,
        query: query,
      ),
    );
    // 默认先添加机器人的消息
    chatMessages.insert(
      0,
      ChatMessageData(
        event: MessageEventType.robot.event,
        messageId: Utils.getUniqueId(),
        query: query,
        createdAt: DateTime.now().millisecondsSinceEpoch,
        isRobotLoading: true,
        robotResponseText: "",
      ),
    );

    // 更新UI
    update([GetxUpdateKeys.chatListId]);

    // 请求获取机器人的回答
    requestGetRobotResponse(
      query,
      userId: Utils.userId,
      conversationId: conversationId,
      isStream: isStream,
      streamSuccess: (data) async {
        chatMessages.first.isRobotLoading = false;
        _handlerProcessChatStreamResponse(
          data,
          onTextUpdate: (value) {
            chatMessages.first.robotResponseText = value.$1;
            // 记录当前会话的taskId
            currentTaskId = value.$2['task_id'] ?? '';
            // 更新UI
            update([GetxUpdateKeys.chatListId]);
          },
          messageEnd: (value) {
            // 完成回答,响应结束。
            isResponding.value = false;
            // 处理message_end事件
            _handlerMessageEnd(value);
          },
        );
      },
      success: (data) {
        chatMessages.first.isRobotLoading = false;
        // 更新UI
        chatMessages.first.robotResponseText = data["answer"];
        // 记录当前会话的taskId
        currentTaskId = data['task_id'] ?? '';
        // 更新UI
        update([GetxUpdateKeys.chatListId]);
        // 处理message_end事件
        isResponding.value = false;
        _handlerMessageEnd(data);
      },
      fail: (code, msg) {
        chatMessages.first.isRobotLoading = false;
        chatMessages.first.robotResponseText = msg;
        isResponding.value = false;
        update([GetxUpdateKeys.chatListId]);
      },
      complete: () {},
    );
  }

  ///
  /// 停止机器人响应
  ///
  void stopRobotResponse() {
    isUserDragging = false;

    if (!Utils.isBlank(currentTaskId)) {
      requestStopRobotResponse(
        currentTaskId!,
        userId: Utils.userId,
        success: (data) {
          isResponding.value = false;
        },
        fail: (code, msg) {},
      );
    } else {
      // 没有taskId，则直接停止当前会话
      isResponding.value = false;
      chatMessages.removeLast();
      update([GetxUpdateKeys.chatListId]);
    }
  }

  ///
  /// 点击某个会话【获取某会话的历史消息】
  ///
  void onChatSessionClick(
    String conversationId, {
    String title = '',
  }) {
    isUserDragging = false;
    // 获取会话历史消息
    requestGetChatHistory(
      userId: Utils.userId,
      conversationId: conversationId,
      success: (data) {
        // 添加会话历史
        chatMessages.assignAll(data);
        chatMessages = chatMessages.reversed.toList();
        // 修改当前导航栏title
        barTitle.value = title;
        // 记录最新一条机器人回答的conversationId
        Utils.lastConversationId = conversationId;
        // 更新UI
        update([GetxUpdateKeys.chatListId]);
      },
      fail: (code, msg) {},
    );
  }

  ///
  /// 删除某一个会话
  ///
  void deleteSession(
    ChatSessionData? session, {
    required int index,
  }) {
    final sessionId = session?.id ?? '';
    if (sessionId.isNotEmpty) {
      requestDeleteChatSession(
        session!.id!,
        userId: Utils.userId,
        success: (data) {
          final conversationId = chatSessionList[index].id;
          // 删除成功
          chatSessionList.removeAt(index);
          // 更新UI
          update([GetxUpdateKeys.chatSessionListId]);
          // 如果当前删除的会话正处于聊天状态，则执行新会话操作
          // 判断会话列表是否为空，重置lastConversationId || 当前删除的是正在聊天的会话
          if (chatSessionList.isEmpty || conversationId == Utils.lastConversationId) {
            createNewChat();
            Utils.lastConversationId = null;
            // 设置导航栏标题
            barTitle.value = chatRoomInfoData.value.name ?? '';
          }
        },
        fail: (code, msg) {},
      );
    }
  }

  ///
  /// 新对话：清空与机器人的聊天记录【保留第一条推荐问题】
  ///
  void createNewChat() {
    chatMessages.clear();
    // 重置某会话机器人的conversationId
    Utils.lastConversationId = null;
    if (welcomeData != null) {
      chatMessages.add(welcomeData!);
    }
    // 更新导航栏标题
    barTitle.value = '新会话';
    // 更新聊天UI
    update([GetxUpdateKeys.chatListId]);
  }

  ///
  /// 重新命名某个会话
  ///
  /// inputName: 用户输入的问题。
  ///
  void renameSession(
    String conversationId, {
    String inputQuery = '',
  }) {
    requestRenameChatSession(
      conversationId,
      userId: Utils.userId,
      success: (data) {
        if (!Utils.isBlank(data.name)) {
          final session = chatSessionList.firstWhere(
            (element) => element.id == conversationId,
            orElse: () => ChatSessionData(
              name: data.name,
              id: data.id,
              createdAt: data.createdAt,
            ),
          );
          session.name = data.name;
          session.id = data.id;
          session.createdAt = data.createdAt;
          // 如果是当前会话，则更新导航栏title
          barTitle.value = data.name ?? '新会话';
          // 更新UI
          update([GetxUpdateKeys.chatSessionListId]);
        }
      },
      fail: (code, msg) {},
    );
  }

  ///
  /// 当前回答的下一轮建议问题列表
  ///
  void getNextSuggestedQuestions(String messageId) {
    // 获取当前机器人回答的下一轮推荐问题列表
    reuqestGetNextSuggestedQuestions(
      messageId,
      userId: Utils.userId,
      success: (data) {
        final answerMessage = chatMessages.first;
        answerMessage.suggestedQuestions = data;
        Logger().d('下一轮推荐问题：$data');
        // 更新UI
        update([GetxUpdateKeys.chatListId]);
      },
      fail: (code, msg) {},
    );
  }
}

///
/// Chat Room Getx管理器扩展
///
extension ChatRoomControllerExt on ChatRoomController {
  ///
  /// 处理流式响应
  ///
  /// onTextUpdate -> 逐字添加到缓冲区并触发回调
  ///
  /// messageEnd -> 对话结束
  ///
  Future<void> _handlerProcessChatStreamResponse(
    Stream stream, {
    required ValueChanged<ChatStream> onTextUpdate,
    required ValueChanged<ChatMap> messageEnd,
  }) async {
    // 用于每个阶段的对话结果
    final StringBuffer buffer = StringBuffer();

    // 转换流为字符串流【流的核心解析代码】
    final transformStream = stream
        .transform(
          StreamTransformer<Uint8List, String>.fromHandlers(
            handleData: (data, sink) => sink.add(utf8.decode(data)),
          ),
        )
        .transform(const LineSplitter());

    // 处理流式响应
    await for (final event in transformStream) {
      if (event.isNotEmpty && event.startsWith('data: ')) {
        // 模型的响应数据每次都以data:开头，后面跟着一个json字符串，所以需要先移除data:
        List<String> jsonData = event.split('data: ');
        // 移除空字符串
        jsonData = jsonData.where((element) => element.isNotEmpty).toList();

        try {
          for (var element in jsonData) {
            // 解析 JSON 数据
            final json = jsonDecode(element);
            final event = json['event'] ?? '';

            // 处理不同类型的事件
            switch (event) {
              case 'workflow_started':
              case 'node_started':
              case 'node_finished':
              case 'workflow_finished':
                Logger().d('处理 $event 事件: $json');
                break;
              case 'message':
                // 获取当前阶段的对话结果，content就是当前阶段的对话结果
                final content = json['answer'] as String;

                if (content.isNotEmpty) {
                  // 逐字添加到缓冲区并触发回调
                  for (int i = 0; i < content.length; i++) {
                    // 将每次的 content 添加到缓冲区中
                    buffer.write(content[i]);
                    // 回调对话结果
                    onTextUpdate((buffer.toString(), json));
                    // 控制打印速度
                    await Future.delayed(const Duration(milliseconds: 50));
                  }
                }
                break;
              case 'message_end':
                messageEnd(json);
                break;
              case 'tts_message': // TTS 音频流事件，即：语音合成输出
              case 'tts_message_end': // TTS 音频流结束事件
                Logger().d('处理 $event 事件: $json');
                break;
              default:
                Logger().d('未知事件: $event');
            }
          }
        } catch (e) {
          Logger().e('Error parsing JSON: $e');
        }
      }
    }
  }

  ///
  /// 处理机器人回答结束【message_end】逻辑操作
  ///
  void _handlerMessageEnd(Map<String, dynamic> value) {
    // 更新默认机器人消息为message_end属性值。
    final answerMessage = chatMessages.first;
    answerMessage.conversationId = value['conversation_id'];
    answerMessage.messageId = value['message_id'];
    answerMessage.createdAt = value['created_at'];
    answerMessage.taskId = value['task_id'];
    answerMessage.id = value['id'];
    // 获取下一轮推荐问题列表
    getNextSuggestedQuestions(answerMessage.messageId);
    // 用于更新当前会话的名称
    if (Utils.isBlank(Utils.lastConversationId)) {
      // 聊天在同一个会话中，则不添加新会话，反之添加新的会话。同一个会话中 conversationId都是一样的
      chatSessionList.insert(
        0,
        ChatSessionData(
          id: value['conversation_id'],
          name: '新会话',
          createdAt: value['created_at'],
        ),
      );
      // 更新导航栏title
      barTitle.value = '新会话';
      // 更新当前会话的名称
      renameSession(answerMessage.conversationId);
    }
    // 记录最新一条机器人回答的conversationId
    Utils.lastConversationId = answerMessage.conversationId;
  }
}
